package com.victor.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
@RefreshScope
public class ResponseFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return -2;
    }

    @Value("${desensitization.enabled:false}")
    private Boolean desensitization;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        if (!desensitization) {
            return chain.filter(exchange);
        }else {

            ServerHttpResponse originalResponse = exchange.getResponse();
            DataBufferFactory bufferFactory = originalResponse.bufferFactory();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

                    if (body instanceof Flux) {
                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            //dataBuffer合并成一个，解决获取结果不全问题
                            DataBuffer join = dataBufferFactory.join(dataBuffers);
                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);
                            //释放掉内存
                            DataBufferUtils.release(join);
                            String lastStr = new String(content, Charset.forName("UTF-8"));

                            try {
                                JSONObject jsonObject = JSONObject.parseObject(lastStr);
                                log.info("原始Response:{}", jsonObject);
                                //在此处处理返回结果
                                int code = jsonObject.getInteger("code");
                                if (HttpStatus.OK.value() == code) {
                                    JSONObject data = jsonObject.getJSONObject("data");
                                    if (data != null) {
                                        JSONArray records = data.getJSONArray("records");
                                        //判断是否为Page
                                        if (records != null && records.size() > 0) {
                                            for (int i = 0; i < records.size(); i++) {
                                                JSONObject record = records.getJSONObject(i);
                                                volatileInfo(record);
                                            }
                                        } else {
                                            volatileInfo(data);
                                        }
                                    }
                                    return bufferFactory.wrap(jsonObject.toString().getBytes(StandardCharsets.UTF_8));
                                }


                            } catch (Exception e) {
                                log.error("e", e);
                            }
                            //不处理异常则用json转换前的数据返回
                            return bufferFactory.wrap(content);
                        }));
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        }
    }


    private void volatileInfo(JSONObject object) {
        //身份证脱敏
        if (StrUtil.isNotBlank(object.getString("idcard"))) {
            String idCard = object.getString("idcard");
            if (idCard.length() == 15) {
                idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1******$2");
            } else if (idCard.length() == 18) {
                idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1*********$2");
            } else {
                idCard = "**************************";
            }
            object.put("idcard", idCard);
        }

        if (StrUtil.isNotBlank(object.getString("hostIdcard"))) {
            String idCard = object.getString("idcard");
            if (idCard.length() == 15) {
                idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1******$2");
            } else if (idCard.length() == 18) {
                idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1*********$2");
            } else {
                idCard = "**************************";
            }
            object.put("hostIdcard", idCard);
        }

        //姓名脱敏
        if (StrUtil.isNotBlank(object.getString("name"))) {
            String fullName = object.getString("name");
            String name = StringUtils.left(fullName, 1);
            object.put("name", StringUtils.rightPad(name, StringUtils.length(fullName), "*"));
        }

        //手机号脱敏
        if (StrUtil.isNotBlank(object.getString("phone"))) {
            String phone = object.getString("phone");
            phone = phone.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
            object.put("phone", phone);
        }

        //密码脱敏
        if (StrUtil.isNotBlank(object.getString("password"))) {
            object.put("password", "*****************");
        }


    }


}